package org.redmagic.agent.spring;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.springframework.util.PropertyPlaceholderHelper;
import org.springframework.util.StringUtils;

public class RedMagicPlaceholderResolver extends PropertyPlaceholderHelper {
	
	private static final Map<String, String> wellKnownSimplePrefixes = new HashMap<String, String>(4);

	static {
		wellKnownSimplePrefixes.put("}", "{");
		wellKnownSimplePrefixes.put("]", "[");
		wellKnownSimplePrefixes.put(")", "(");
	}
	
	private final String placeholderPrefix;
	
	private final String placeholderSuffix;
	
	private final String simplePrefix;
	
	public RedMagicPlaceholderResolver(String placeholderPrefix, String placeholderSuffix) {
		super(placeholderPrefix, placeholderSuffix);
		
		this.placeholderPrefix = placeholderPrefix;
		this.placeholderSuffix = placeholderSuffix;
		
		String simplePrefixForSuffix = wellKnownSimplePrefixes.get(this.placeholderSuffix);
		if (simplePrefixForSuffix != null && this.placeholderPrefix.endsWith(simplePrefixForSuffix)) {
			this.simplePrefix = simplePrefixForSuffix;
		}
		else {
			this.simplePrefix = this.placeholderPrefix;
		}
	}
	
	public void resolvePlaceholders(String value, Set<String> placeholders) {
		
		StringBuilder buf = new StringBuilder(value);

		int startIndex = value.indexOf(this.placeholderPrefix);
		while (startIndex != -1) {
			int endIndex = findPlaceholderEndIndex(buf, startIndex);
			if (endIndex != -1) {
				String placeholder = buf.substring(startIndex + this.placeholderPrefix.length(), endIndex);
				if (!placeholders.add(placeholder)) {
//					throw new IllegalArgumentException(
//							"Circular placeholder reference '" + placeholder + "' in property definitions");
					return; // TODO FIXME
				}
				
				// Recursive invocation, parsing placeholders contained in the placeholder key.
				resolvePlaceholders(placeholder, placeholders);
			}
			else {
				startIndex = -1;
			}
		}
	}

	private int findPlaceholderEndIndex(CharSequence buf, int startIndex) {
		int index = startIndex + this.placeholderPrefix.length();
		int withinNestedPlaceholder = 0;
		while (index < buf.length()) {
			if (StringUtils.substringMatch(buf, index, this.placeholderSuffix)) {
				if (withinNestedPlaceholder > 0) {
					withinNestedPlaceholder--;
					index = index + this.placeholderSuffix.length();
				}
				else {
					return index;
				}
			}
			else if (StringUtils.substringMatch(buf, index, this.simplePrefix)) {
				withinNestedPlaceholder++;
				index = index + this.simplePrefix.length();
			}
			else {
				index++;
			}
		}
		return -1;
	}
}
